<template>
  <div
    id="screenshot"
    ref="screenshot"
    @dragenter="handleDragenter"
    @drop="handleMaindrag"
    @dragover="handleMaindrag"
    @dragleave="handleMaindrag"
  >
    <div class="clip" ref="clip">
      <canvas class="bgcanvas" ref="bgcanvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }">
      </canvas>
      <canvas
        class="canvas"
        ref="canvas"
        :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
        @mousedown="handleMousedown"
        @mousemove="handleMousemove"
      >
      </canvas>
    </div>
    <div class="result" ref="result">
      <canvas
        class="rcanvas"
        ref="rcanvas"
        :style="{ width: resultWidth + 'px', height: resultHeight + 'px' }"
        @dblclick="handleDBclick"
      ></canvas>
    </div>
    <div class="tip" v-show="tipShow" @dragleave="handleDragleave" @drop="handleDrop">
      <span>请拖入图片</span>
    </div>
  </div>
</template>
<script>
import { mapState } from "vuex";
export default {
  setup() {},
  computed: {
    ...mapState({
      windowWidth: "windowWidth",
      windowHeight: "windowHeight",
    }),
  },
  watch: {
    windowWidth() {
      this.resizeCanvas();
    },
    windowWidth() {
      this.resizeCanvas();
    },
  },
  data() {
    return {
      tipShow: true,
      img: undefined,
      vtb: 1,
      context: undefined,
      bgcontext: undefined,
      rcontext: undefined,
      baseLineWidth: 2,
      lineWidth: this.baseLineWidth,
      canvasWidth: 0,
      canvasHeight: 0,
      resultWidth: 0,
      resultHeight: 0,
      canDraw: false,
      mousedata: {},
    };
  },
  methods: {
    handleMaindrag(e) {
      e.preventDefault();
      e.stopPropagation();
    },
    handleDragleave(e) {
      this.tipShow = false;
      e.stopPropagation();
      e.preventDefault();
    },
    handleDragenter(e) {
      this.tipShow = true;
      e.stopPropagation();
      e.preventDefault();
    },
    handleDrop(e) {
      if (e.dataTransfer.getData("Url")) {
        // img.src = e.dataTransfer.getData("Url");
        // img.onload = loadend;
      } else {
        const data = e.dataTransfer;
        const files = data.files;
        // 将其传给真正的处理文件的函数
        const file = files[0];
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          this.img.src = reader.result;
          this.img.onload = this.imgLoadend;
          this.tipShow = false;
        };
      }
      e.stopPropagation();
      e.preventDefault();
    },
    imgLoadend() {
      this.$refs.bgcanvas.width = this.img.width;
      this.$refs.bgcanvas.height = this.img.height;
      this.$refs.canvas.width = this.img.width;
      this.$refs.canvas.height = this.img.height;
      this.resizeCanvas();
      this.drawImg();
    },
    resizeCanvas() {
      let b = this.img.width / this.img.height;
      let pb = this.$refs.clip.clientWidth / this.$refs.clip.clientHeight;
      if (b > pb) {
        this.canvasWidth = this.$refs.clip.clientWidth;
        this.canvasHeight = this.$refs.clip.clientWidth / b;
        this.canvasWidth = this.$refs.clip.clientWidth;
        this.canvasHeight = this.$refs.clip.clientWidth / b;
        this.vtb = this.img.width / this.$refs.clip.clientWidth;
      } else {
        this.canvasWidth = this.$refs.clip.clientHeight * b;
        this.canvasHeight = this.$refs.clip.clientHeight;
        this.canvasWidth = this.$refs.clip.clientHeight * b;
        this.canvasHeight = this.$refs.clip.clientHeight;
        this.vtb = this.img.height / this.$refs.clip.clientHeight;
      }
      this.context.font = this.vtb * 16 + "px Verdana";
      this.lineWidth = this.baseLineWidth * this.vtb;
    },
    resizeResult() {
      let b = this.$refs.rcanvas.width / this.$refs.rcanvas.height;
      let pb = this.$refs.result.clientWidth / this.$refs.result.clientHeight;
      if (b > pb) {
        this.resultWidth = this.$refs.result.clientWidth;
        this.resultHeight = this.$refs.result.clientWidth / b;
      } else {
        this.resultWidth = this.$refs.result.clientHeight * b;
        this.resultHeight = this.$refs.result.clientHeight;
      }
    },
    drawImg() {
      this.bgcontext.drawImage(this.img, 0, 0, this.img.width, this.img.height);
    },
    handleMousedown(e) {
      this.canDraw = true;
      this.mousedata = {
        x: e.layerX + this.$refs.canvas.clientWidth / 2,
        y: e.layerY + this.$refs.canvas.clientHeight / 2,
      };
      if (e.which == 3) {
        this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
      }
    },
    handleMousemove(e) {
      if (this.canDraw) {
        //矩形宽度
        const clipwidth = e.layerX + this.$refs.canvas.clientWidth / 2 - this.mousedata.x;
        //矩形高度
        const clipheight = e.layerY + this.$refs.canvas.clientHeight / 2 - this.mousedata.y;

        //所有的数据都得乘以缩放比例
        const clip = {
          x: clipwidth > 0 ? this.mousedata.x * this.vtb : (this.mousedata.x + clipwidth) * this.vtb, //如果鼠标在按下位置的左边则x复制为鼠标当前x
          y: clipheight > 0 ? this.mousedata.y * this.vtb : (this.mousedata.y + clipheight) * this.vtb, //如果鼠标在按下位置的上边则y复制为鼠标当前y
          width: Math.abs(clipwidth) * this.vtb,
          height: Math.abs(clipheight) * this.vtb,
        };
        if (Math.abs(clip.width) < 1 || Math.abs(clip.height) < 1) {
          return;
        }
        //绘制遮罩
        this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
        this.context.globalCompositeOperation = "source-over";
        this.context.fillStyle = "rgba(0,0,0,0.3)";
        this.context.fillRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height);
        //绘制虚线

        this.context.lineWidth = this.lineWidth;
        this.context.setLineDash([this.lineWidth, this.lineWidth]);
        this.context.strokeStyle = "#409eff"; // 设置颜色
        this.context.strokeRect(
          clip.x - this.lineWidth / 2,
          clip.y - this.lineWidth / 2,
          clip.width + this.lineWidth,
          clip.height + this.lineWidth
        ); // 绘制一个矩形的边框
        //绘制显示区域
        this.context.globalCompositeOperation = "destination-out";
        this.context.fillStyle = "rgba(0,0,0)";
        this.context.fillRect(clip.x, clip.y, clip.width, clip.height);
        this.context.fill();
        //裁切图片并显示
        const imgd = this.bgcontext.getImageData(clip.x, clip.y, clip.width, clip.height);
        this.$refs.rcanvas.width = imgd.width;
        this.$refs.rcanvas.height = imgd.height;
        this.rcontext.putImageData(imgd, 0, 0);
        this.resizeResult();

        //绘制提示文本
        this.context.globalCompositeOperation = "source-over";
        this.context.fillStyle = "#fff";
        this.context.fillText(Math.floor(clip.width) + "*" + Math.floor(clip.height), clip.x, clip.y - this.lineWidth);
      }
    },
    handleDBclick(){
        this.DownLoadQrCode(this.$refs.rcanvas);
    },
    DownLoadQrCode(canvas, name = "img") {
      //将画布转化为base64格式
      var url = canvas.toDataURL("image/png");
      //JavaScript初始化下载方法
      var a = document.createElement("a");
      document.body.appendChild(a);
      a.href = url;
      a.download = name + ".png";
      //执行下载
      a.click();
    },
    
  },
  mounted() {
    const _this = this;
    this.img = new Image();
    this.context = this.$refs.canvas.getContext("2d");
    this.bgcontext = this.$refs.bgcanvas.getContext("2d");
    this.rcontext = this.$refs.rcanvas.getContext("2d");

    window.addEventListener("mouseup", function (e) {
      _this.canDraw = false;
    });
  },
};
</script>
<style scoped>
#screenshot {
  display: flex;
  overflow: hidden;
  position: relative;
}
.canvas,
.bgcanvas,
.rcanvas {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
}

.clip,
.result {
  position: relative;
  flex: 1;
  overflow: hidden;
}

.tip {
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.616);
  font-size: 50px;
}

.tip > * {
  pointer-events: none;
}
</style>
